/* $Header: 0x_cmds.c,v 2.12 04/03/18 10:50:26 przybyls Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME: 0x_cmds.c                                              */
/* ============                                                        */
/*                                                                     */
/* Author:  Tom Przybylski                                             */
/*                                                                     */
/* MODULE PURPOSE: This module will handle the commands for the        */
/*          sampler on EOS.                                            */
/*                                                                     */
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/

#include <typedefs.h>
#include <p_wkfile.h>
#include <wkfile.h>
#include <ramps.h>
#include <zone_config.h>
#include <zone_status.h>
#include <p_status.h>
#include <status.h>
#include <std_ops.h>
#include <string.h>
#include <task_pub.h>
#include <error.h>
#include <i_op.h>
#include <config.h>
#include <mio.h>
#include <cmd_set.h>
#include <cmdproc.h>
#include <method.h>
#include <hostutil.h>
#include <diag.h>
#include <als_ui.h>
#include <sampler.h>
#include <als.h>
#include <clock_ui.h>
#include <p_ui.h>
#include <run_ui.h>
#include <messages.h>
#include <display.h>
#include <duart.h>

/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/



/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/


/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/

extern CMD_QUEUE_TYPE  _0X_Cmd_Q;

/*****************************/
/*   LOCAL DEFINES           */
/*****************************/

/*****************************/
/*   STATIC VARIABLES        */
/*****************************/

/*****************************/
/*   MACROS                  */
/*****************************/



/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/


/***********************************************************************/
/* FUNCTION: Sampler parser routines from Mike's code                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Used to replicate sampler's odd commands.                  */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

enum {IntToken=1, CharToken, CommaToken, SemiToken, PeriodToken, EqualToken, NameToken, NullToken};
#define TOK_NAMESIZE  32
typedef struct {const char *s;     /* pointer to string  */
                      short typ;   /* type of token      */
                      union {int  ival;
                             char cval;
                             char nval[TOK_NAMESIZE];} u; }token_t;

typedef struct {const char   *pname;
                const short  lbnd;
                const short  ubnd; } param_t;

const param_t parray[] = {{ "draw", 100, 10000},
                          { "wsh_disp", 10, 10000},
                          { "wsh_vol", 2, 7},
                          { "inj_disp", 10, 30000} };  /* inj_disp==0 for normal/slow plunger */

INT16 GetToken(token_t  *t)
{
         char *ts, blank = ' ', zero = '0', nine = '9', ucA = 'A', ucZ = 'Z';
   const char *s;
         int   i;

        for (s = t->s; *s++ == blank; ){}; s--;  /* skip past blanks */
        if ((*s == '-') || (*s == '+')) {
          t->u.cval = *s++;
          if ((*s >= zero) && (*s <= nine)) {
            for (i = 0; (*s >= zero) && (*s <= nine); s++) i = i * 10 + *s - zero;
            if (t->u.cval == '-') i = - i;
            t->u.ival = i; t->typ = IntToken; }
          else {
             t->typ = CharToken; } }
        else if ((*s >= zero) && (*s <= nine)) {
          for (i = 0; (*s >= zero) && (*s <= nine); s++) i = i * 10 + *s - zero;
          t->u.ival = i; t->typ = IntToken; }
        else if ((*s >= ucA) && (*s <= ucZ)   || (*s >= 'a') && (*s <= 'z')   || (*s == '_')){
          ts = t->u.nval;  t->typ = NameToken;  i = TOK_NAMESIZE - 1;
          while (((*s >= zero) && (*s <= nine)) ||
                 ((*s >= ucA) && (*s <= ucZ))   ||
                 ((*s >= 'a') && (*s <= 'z'))   ||
                  (*s == '_'))
            if (i>0) {*ts++ = *s++; --i; } else s++;
          *ts = '\0'; }
        else if (*s != '\0') { t->u.cval = *s++;  t->typ = CharToken; }
        else t->typ = NullToken;
        if (t->typ == CharToken) {
          if (t->u.cval == ',') t->typ = CommaToken;
          else if (t->u.cval == ';') t->typ = SemiToken;
          else if (t->u.cval == '=') t->typ = EqualToken;
          else if (t->u.cval == '.') t->typ = PeriodToken; };
        t->s = s;  return t->typ;
}


/***********************************************************************/
/* FUNCTION: Do0xEO                                                    */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Echo command.                                              */
/*                                                                     */
/* RETURNED VALUE: length of response string                           */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

INT16 Do0xEO(CMD_TYPE *p_cmd,BIT8  *p_resp_parm)
{
U_INT16 len;

   len = 0;

   if (p_cmd->parmv[0] == 1)
   {
      len = PutAsciiParam((BIT8 *)"\"", p_resp_parm);
      len += PutAsciiParam((BIT8 *)&(p_cmd->parms[p_cmd->parmv[1]]),
                                     p_resp_parm+len);
      len += PutAsciiParam((BIT8 *)"\"", p_resp_parm+len);
      return len;
   }
   else
   {
      CmdErrorHandler(p_cmd,1,INVALID_PARAM);
      return NO_RESPONSE;
   }
}

/***********************************************************************/
/* END FUNCTION: Do0xEO                                                */
/***********************************************************************/



/***********************************************************************/
/* FUNCTION: Do0XOldId                                                 */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS *IDN   command                                         */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/


INT16 Do0XOldId (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT16  len;
   BIT8   *ptr;

   (void) p_cmd;

   ptr = p_resp_parm;

   /* Back up over opcode */
   do
   {
      --p_resp_parm;
   } while (*p_resp_parm != '*');

   len = PutAsciiParam((BIT8 *)"Hewlett-Packard Co., HP6890N, 0, ",p_resp_parm);

   len += TransferVersion( p_resp_parm+len );

   /* Need to return length of added strings minus backup over *IDN? */
   /* This returns xx00Hewlett-Packard Co., HP6890N, 0, N.04.00   */
   return  len + (INT16) (p_resp_parm-ptr);
}

/***********************************************************************/
/* END FUNCTION: Do0xOldId                                             */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XCO                                                    */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS CONFIG command                                         */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 AddControllerID (BIT8 *p_resp_parm)
{
   INT16  len;

   len = 0;

   if (PE_Defect_Fix != OFF)
   {
      /* Instrument Model Number and Firmware rev */
      len += PutAsciiParam((BIT8 *)"G2612", p_resp_parm+len);
   }
   else
   {
      /* Instrument Model Number */
      len += PutAsciiParam((BIT8 *)"G1530",p_resp_parm+len);
   }

      /* Firmware rev */
      len += TransferVersion( p_resp_parm+len );

   /* tray, BCR:        */
   len += PutAsciiParam((BIT8 *)",",p_resp_parm+len);
   len += PutIntParam (Tray_Max_Bottle, p_resp_parm+len, 0);
   len += PutAsciiParam((BIT8 *)",",p_resp_parm+len);
   len += PutIntParam (BCR_Type, p_resp_parm+len, 0);

   return  len;
}


INT16 Do0XCO (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT16  len;
   INT32  entry;
   UI_ERR error;

   len = 0;

   if (p_cmd->parmv[0] > 0)
   {
      error = DecToInt(&p_cmd->parms[p_cmd->parmv[1]],0,&entry);
      /* check for valid parameters */
      if( ((U_INT16)error == 0 ) && ((entry >= 1 ) && (entry <= 3)) )
      {
         switch (entry)
         {
         case 1:
            if (HaveFrAlsInjector())
            {
               len = AddInjectorID (FRONT, p_resp_parm);
            }
            else
            {
               len = PutIntParam (Err_NoTower, p_resp_parm, 0);
            }
            break;

         case 2:
            if (HaveBkAlsInjector())
            {
               len = AddInjectorID (BACK, p_resp_parm);
            }
            else
            {
               len = PutIntParam (Err_NoTower, p_resp_parm, 0);
            }
            break;

         case 3:
         default:
            len = AddControllerID (p_resp_parm);
            break;
         }
      }
      else
      {
         len = PutIntParam (Err_InvParameter, p_resp_parm, 0);
      }

   }
   else
   {
      if (HaveFrAlsInjector())
      {
         len = AddInjectorID (FRONT, p_resp_parm);
      }

      len += PutAsciiParam((BIT8 *)";",p_resp_parm+len);

      if (HaveBkAlsInjector())
      {
         len += AddInjectorID (BACK, p_resp_parm+len);
      }

      len += PutAsciiParam((BIT8 *)";",p_resp_parm+len);
      len += AddControllerID (p_resp_parm+len);
   }

   return  len;
}


/***********************************************************************/
/* END FUNCTION: Do0xCO                                                */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XCPI1                                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS CPI1 command                                           */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XCPI1 (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   MIO_HDR_TYPE *p_out_hdr;
   BIT8         *p_out_buf;
   INT16  len;

   (void) p_resp_parm;

   Cpi1_Reply.comm_port     = p_cmd->comm_port;
   Cpi1_Reply.dsap.int_dsap = p_cmd->dsap.int_dsap;
   Cpi1_Reply.ssap.int_ssap = p_cmd->ssap.int_ssap;

   while ( (p_out_hdr = AcquirePutBuf(&p_out_buf)) == NULL)
   {
      Task_yield();
   }

   if( (len = StrLen(&p_cmd->parms[p_cmd->parmv[1]])) >= 4)
   {
      Cpi1_Reply.ssap2.char_ssap[0] = p_cmd->parms[p_cmd->parmv[1]+2]; /* save pass through SSAP */
      Cpi1_Reply.ssap2.char_ssap[1] = p_cmd->parms[p_cmd->parmv[1]+3];

      StrNCpy (p_out_buf, &p_cmd->parms[p_cmd->parmv[1]], len);

      (void) PutAsciiParam ((BIT8 *)"Q0", p_out_buf+2);  /* substitute Q0 SSAP */

      if (TowersSwapped()) PutMsg (p_out_hdr, INJECTOR2_PORT, len);
      else                 PutMsg (p_out_hdr, INJECTOR1_PORT, len);
   }
   else
   {
      CmdErrorHandler(p_cmd,1,SYNTAX_ERROR);
   }

   return NO_RESPONSE;

}

INT16 Do0XCPI1a (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   MIO_HDR_TYPE *p_out_hdr;
   BIT8         *p_out_buf;
   INT16  len;

   (void) p_resp_parm;

   Cpi1a_Reply.comm_port     = p_cmd->comm_port;
   Cpi1a_Reply.dsap.int_dsap = p_cmd->dsap.int_dsap;
   Cpi1a_Reply.ssap.int_ssap = p_cmd->ssap.int_ssap;

   while ( (p_out_hdr = AcquirePutBuf(&p_out_buf)) == NULL)
   {
      Task_yield();
   }

   if( (len = StrLen(&p_cmd->parms[p_cmd->parmv[1]])) >= 4)
   {
      Cpi1a_Reply.ssap2.char_ssap[0] = p_cmd->parms[p_cmd->parmv[1]+2]; /* save pass through SSAP */
      Cpi1a_Reply.ssap2.char_ssap[1] = p_cmd->parms[p_cmd->parmv[1]+3];

      StrNCpy (p_out_buf, &p_cmd->parms[p_cmd->parmv[1]], len);

      (void) PutAsciiParam ((BIT8 *)"Q3", p_out_buf+2);  /* substitute Q3 SSAP */

      if (TowersSwapped()) PutMsg (p_out_hdr, INJECTOR2_PORT, len);
      else                 PutMsg (p_out_hdr, INJECTOR1_PORT, len);
   }
   else
   {
      CmdErrorHandler(p_cmd,1,SYNTAX_ERROR);
   }

   return NO_RESPONSE;

}


/***********************************************************************/
/* END FUNCTION: Do0xCPI1                                              */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XCPI2                                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS CPI2 command                                           */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XCPI2 (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   MIO_HDR_TYPE *p_out_hdr;
   BIT8         *p_out_buf;
   INT16  len;

   (void) p_resp_parm;

   Cpi2_Reply.comm_port     = p_cmd->comm_port;
   Cpi2_Reply.dsap.int_dsap = p_cmd->dsap.int_dsap;
   Cpi2_Reply.ssap.int_ssap = p_cmd->ssap.int_ssap;

   while ( (p_out_hdr = AcquirePutBuf(&p_out_buf)) == NULL)
   {
      Task_yield();
   }

   if( (len = StrLen(&p_cmd->parms[p_cmd->parmv[1]])) >= 4)
   {
      Cpi2_Reply.ssap2.char_ssap[0] = p_cmd->parms[p_cmd->parmv[1]+2]; /* save pass through SSAP */
      Cpi2_Reply.ssap2.char_ssap[1] = p_cmd->parms[p_cmd->parmv[1]+3];

      StrNCpy (p_out_buf, &p_cmd->parms[p_cmd->parmv[1]], len);

      (void) PutAsciiParam ((BIT8 *)"Q0", p_out_buf+2);  /* substitute Q0 SSAP */

      if (TowersSwapped()) PutMsg (p_out_hdr, INJECTOR1_PORT, len);
      else                 PutMsg (p_out_hdr, INJECTOR2_PORT, len);
   }
   else
   {
      CmdErrorHandler(p_cmd,1,SYNTAX_ERROR);
   }

   return NO_RESPONSE;

}

INT16 Do0XCPI2a (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   MIO_HDR_TYPE *p_out_hdr;
   BIT8         *p_out_buf;
   INT16  len;

   (void) p_resp_parm;

   Cpi2a_Reply.comm_port     = p_cmd->comm_port;
   Cpi2a_Reply.dsap.int_dsap = p_cmd->dsap.int_dsap;
   Cpi2a_Reply.ssap.int_ssap = p_cmd->ssap.int_ssap;

   while ( (p_out_hdr = AcquirePutBuf(&p_out_buf)) == NULL)
   {
      Task_yield();
   }

   if( (len = StrLen(&p_cmd->parms[p_cmd->parmv[1]])) >= 4)
   {
      Cpi2a_Reply.ssap2.char_ssap[0] = p_cmd->parms[p_cmd->parmv[1]+2]; /* save pass through SSAP */
      Cpi2a_Reply.ssap2.char_ssap[1] = p_cmd->parms[p_cmd->parmv[1]+3];

      StrNCpy (p_out_buf, &p_cmd->parms[p_cmd->parmv[1]], len);

      (void) PutAsciiParam ((BIT8 *)"Q3", p_out_buf+2);  /* substitute Q3 SSAP */

      if (TowersSwapped()) PutMsg (p_out_hdr, INJECTOR1_PORT, len);
      else                 PutMsg (p_out_hdr, INJECTOR2_PORT, len);
   }
   else
   {
      CmdErrorHandler(p_cmd,1,SYNTAX_ERROR);
   }

   return NO_RESPONSE;

}


/***********************************************************************/
/* END FUNCTION: Do0xCPI2                                              */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XCPTR                                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS CPTR command                                           */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XCPTR (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   MIO_HDR_TYPE *p_out_hdr;
   BIT8         *p_out_buf;
   INT16  len;

   (void) p_resp_parm;

   Cptr_Reply.comm_port     = p_cmd->comm_port;
   Cptr_Reply.dsap.int_dsap = p_cmd->dsap.int_dsap;
   Cptr_Reply.ssap.int_ssap = p_cmd->ssap.int_ssap;

   while ( (p_out_hdr = AcquirePutBuf(&p_out_buf)) == NULL)
   {
      Task_yield();
   }

   if( (len = StrLen(&p_cmd->parms[p_cmd->parmv[1]])) >= 4)
   {
      Cptr_Reply.ssap2.char_ssap[0] = p_cmd->parms[p_cmd->parmv[1]+2]; /* save pass through SSAP */
      Cptr_Reply.ssap2.char_ssap[1] = p_cmd->parms[p_cmd->parmv[1]+3];

      StrNCpy (p_out_buf, &p_cmd->parms[p_cmd->parmv[1]], len);

      (void) PutAsciiParam ((BIT8 *)"Q0", p_out_buf+2);  /* substitute Q0 SSAP */

      PutMsg (p_out_hdr, TRAY_PORT, len);
   }
   else
   {
      CmdErrorHandler(p_cmd,1,SYNTAX_ERROR);
   }

   return NO_RESPONSE;

}

INT16 Do0XCPTRa (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   MIO_HDR_TYPE *p_out_hdr;
   BIT8         *p_out_buf;
   INT16  len;

   (void) p_resp_parm;

   Cptra_Reply.comm_port     = p_cmd->comm_port;
   Cptra_Reply.dsap.int_dsap = p_cmd->dsap.int_dsap;
   Cptra_Reply.ssap.int_ssap = p_cmd->ssap.int_ssap;

   while ( (p_out_hdr = AcquirePutBuf(&p_out_buf)) == NULL)
   {
      Task_yield();
   }

   if( (len = StrLen(&p_cmd->parms[p_cmd->parmv[1]])) >= 4)
   {
      Cptra_Reply.ssap2.char_ssap[0] = p_cmd->parms[p_cmd->parmv[1]+2]; /* save pass through SSAP */
      Cptra_Reply.ssap2.char_ssap[1] = p_cmd->parms[p_cmd->parmv[1]+3];

      StrNCpy (p_out_buf, &p_cmd->parms[p_cmd->parmv[1]], len);

      (void) PutAsciiParam ((BIT8 *)"Q3", p_out_buf+2);  /* substitute Q3 SSAP */

      PutMsg (p_out_hdr, TRAY_PORT, len);
   }
   else
   {
      CmdErrorHandler(p_cmd,1,SYNTAX_ERROR);
   }

   return NO_RESPONSE;

}


/***********************************************************************/
/* END FUNCTION: Do0xCPTR                                              */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XDA                                                    */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS DATE command                                           */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XDA (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT32  entry;
   UI_ERR error;
   DATETIME date;


   if( (p_cmd->parmv[0] == 1) && (p_cmd->parms[p_cmd->parmv[1]] == '?') )
   {
      return PutIntParam (GetAlsTimeSetting(), p_resp_parm, 0);
   }
   else
   {
      error = DecToInt(&p_cmd->parms[p_cmd->parmv[1]],0,&entry);
      /* check for valid parameters */
      if( ((U_INT16)error == 0 ) && ((entry >= ALS_MIN_TIME ) && (entry <= ALS_MAX_TIME)) )
      {
         date = TimeFromSeconds (entry);
         (void) SetFullClockTime (date.second + (100*date.minute) + (10000*date.hour));
         (void) SetDate (GetDate(&date));

         if(((p_cmd->parms[p_cmd->parmv[1]+StrLen(&p_cmd->parms[p_cmd->parmv[1]])-1] == '?') ) ||
            ((p_cmd->parmv[0] == 2) && (p_cmd->parms[p_cmd->parmv[2]] == '?') )                  )
         {
            return PutIntParam (GetAlsTimeSetting(), p_resp_parm, 0);
         }
         else
         {
            return NO_RESPONSE;
         }
      }
      else
      {
         CmdErrorHandler(p_cmd,1,INVALID_PARAM);
         return NO_RESPONSE;
      }

   }

}

/***********************************************************************/
/* END FUNCTION: Do0xDA                                                */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XERROR_STR                                             */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS ERROR_STR command                                      */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XERROR_STR (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT32  entry;
   UI_ERR error;
   INT16  len;
   U_INT16 msg;

   if( (p_cmd->parmv[0] >= 1)  )
   {
      error = DecToInt(&p_cmd->parms[p_cmd->parmv[1]],0,&entry);
      /* check for valid parameters */
      if( (U_INT16)error == 0 )
      {
         msg = MSG_ERROR_STR;

         switch (entry)
         {
         case Err_NoError:
            msg = MSG_NO_ERROR;
            break;
         case IN_PROGRESS:
            msg = MSG_ALS_IN_PROGRESS;
            break;
         case Err_Zhome:
            msg = MSG_ZHOME;
            break;
         case Err_Rhome:
            msg = MSG_RHOME;
            break;
         case Err_Thome:
            msg = MSG_THOME;
            break;
         case Err_BtlInClaw:
            msg = MSG_BTLINCLAW;
            break;
         case Err_ClawEmpty:
            msg = MSG_CLAWEMPTY;
            break;
         case Err_StopKey:
            msg = MSG_STOP_BUTTON;
            break;
         case Err_NoTower:
            msg = MSG_NO_TOWER;
            break;
         case Err_NoTray:
            msg = MSG_NO_TRAY;
            break;
         case Err_NoBCR:
            msg = MSG_NO_BCR;
            break;
         case Err_Ovld:
            msg = MSG_OVLD;
            break;
         case Err_Stalled:
            msg = MSG_STALLED;
            break;
         case Err_NoBarCode:
            msg = MSG_NO_BARCODE;
            break;
         case Err_BCRchip:
            msg = MSG_BCRCHIP;
            break;
         case Err_RangeTray:
            msg = MSG_RANGETRAY;
            break;
         case Err_RangeTpos:
            msg = MSG_RANGETPOS;
            break;
         case Err_InvalidSet:
            msg = MSG_INVALID_SETPTS;
            break;
         case Err_NoComma:
            msg = MSG_NOCOMMA;
            break;
         case Err_NoSemicolon:
            msg = MSG_NOSEMICOLON;
            break;
         case Err_NumError:
            msg = MSG_NUMERROR;
            break;
         case Err_BadLocation:
            msg = MSG_BADLOCATION;
            break;
         case Err_BtlLost:
            msg = MSG_BTLLOST;
            break;
         case Err_InvParameter:
            msg = MSG_INVALID_PARAM;
            break;
         case Err_SetptRange:
            msg = MSG_SETPT_RANGE;
            break;
         case Err_SetptError:
            msg = MSG_SETPT_ERROR;
            break;
         case Err_TimeOut:
            msg = MSG_TIMEOUT;
            break;
         case Err_HangUp:
            msg = MSG_HANGUP;
            break;
         case Err_LogFull:
            msg = MSG_LOGFULL;
            break;
         case Err_EndOfLog:
            msg = MSG_ENDOFLOG;
            break;
         case Err_LogLocked:
            msg = MSG_LOGLOCKED;
            break;
         case Err_Tower:
            msg = MSG_TOWER_ERROR;
            break;
         case Err_Front+COMM_ERR:
            msg = MSG_F_COMM_ERROR;
            break;
         case Err_Front+SYRINGE_ERR:
            msg = MSG_F_SYRINGE_ERROR;
            break;
         case Err_Front+TURRET_ERR:
            msg = MSG_F_TURRET_ERROR;
            break;
         case Err_Front+PLUNGER_ERR:
            msg = MSG_F_PLUNGER_ERROR;
            break;
         case Err_Front+INJECT_ERR:
            msg = MSG_F_INJECT_ERROR;
            break;
         case Err_Front+CPU_ERR:
            msg = MSG_F_CPU_ERROR;
            break;
         case Err_Front+FAULT_ERR:
            msg = MSG_F_DOOR_ERROR;
            break;
         case Err_Front+RESET_ERR:
            msg = MSG_F_RESET_ERROR;
            break;
         case Err_Back+COMM_ERR:
            msg = MSG_B_COMM_ERROR;
            break;
         case Err_Back+SYRINGE_ERR:
            msg = MSG_B_SYRINGE_ERROR;
            break;
         case Err_Back+TURRET_ERR:
            msg = MSG_B_TURRET_ERROR;
            break;
         case Err_Back+PLUNGER_ERR:
            msg = MSG_B_PLUNGER_ERROR;
            break;
         case Err_Back+INJECT_ERR:
            msg = MSG_B_INJECT_ERROR;
            break;
         case Err_Back+CPU_ERR:
            msg = MSG_B_CPU_ERROR;
            break;
         case Err_Back+FAULT_ERR:
            msg = MSG_B_DOOR_ERROR;
            break;
         case Err_Back+RESET_ERR:
            msg = MSG_B_RESET_ERROR;
            break;
         case Err_Injector:
            msg = MSG_TOWER_RESP_ERROR;
            break;
         case Err_NotTrayInj:
            msg = MSG_INCOMPATIBLE_ERROR;
            break;

         default:
            break;
         }

         TransferMsg (msg, p_resp_parm);
         len = StrLen (p_resp_parm);

         if (msg == MSG_ERROR_STR)   /* Use default message */
         {
            len += PutAsciiParam((BIT8 *)" ",p_resp_parm+len);
            len += PutIntParam (entry, p_resp_parm+len, 0);
         }
      }
      else
      {
         len = PutIntParam ((INT32) INVALID_PARAM, p_resp_parm, 0);
      }
   }
   else
   {
      len = PutIntParam ((INT32) INVALID_PARAM, p_resp_parm, 0);
   }

   return len;
}

/***********************************************************************/
/* END FUNCTION: Do0xERROR_STR                                         */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XHOST_CTL                                              */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS HOST_CTL command: Resurrected for 6890N.04.12.         */
/*             0 turns off, any other number turns on.  Returns        */
/*             setpoint as reply.  No errors - no parameter or         */
/*             non-numeric leaves (and returns) current value.         */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XHOST_CTL (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT32  entry;
   UI_ERR error;

   if  (p_cmd->parmv[0] >= 1)
   {
      error = DecToInt(&p_cmd->parms[p_cmd->parmv[1]],0,&entry);

      if (error == 0)
      {
         if (entry == 0) Host_Control = OFF;
         else            Host_Control = ON;
      }
   }

   if (Host_Control == OFF) entry = 0;
   else                     entry = 1;

   return PutIntParam (entry, p_resp_parm, 0);

}

/***********************************************************************/
/* END FUNCTION: Do0xHOST_CTL                                          */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XIC                                                    */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS Inject Config Command (EOS UNIQUE!)                    */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XIC (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT32  entry;
   UI_ERR error;
   INT16  len;
   U_INT16 n;

   if( (p_cmd->parmv[0] == 1) && (p_cmd->parms[p_cmd->parmv[1]] == '?') )
   {
      len = PutIntParam (GetAlsWasteMode(FRONT), p_resp_parm, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetAlsFanOnOff(FRONT), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetSyringeSize(FRONT), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetExtendSolv(FRONT), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetWashStop(FRONT), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (SolventSaverEnabled(FRONT), p_resp_parm+len, 0);

      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetAlsWasteMode(BACK), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetAlsFanOnOff(BACK), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetSyringeSize(BACK), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetExtendSolv(BACK), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetWashStop(BACK), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (SolventSaverEnabled(BACK), p_resp_parm+len, 0);

      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetBCR3of9OnOff(), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetBCR2of5OnOff(), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetBCRUPCOnOff(), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetBCRChecksumOnOff(), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetBCRPosition(), p_resp_parm+len, 0);
      if (GetGripOffset() == 0) len += PutAsciiParam((BIT8 *)",0", p_resp_parm+len);
      else if (GetGripOffset() > 0)  len += PutAsciiParam((BIT8 *)",1", p_resp_parm+len);
           else                      len += PutAsciiParam((BIT8 *)",-1", p_resp_parm+len);
      if (GetFrThetaOffset() == 0) len += PutAsciiParam((BIT8 *)",0", p_resp_parm+len);
      else if (GetFrThetaOffset() > 0)  len += PutAsciiParam((BIT8 *)",1", p_resp_parm+len);
           else                         len += PutAsciiParam((BIT8 *)",-1", p_resp_parm+len);
      if (GetBkThetaOffset() == 0) len += PutAsciiParam((BIT8 *)",0", p_resp_parm+len);
      else if (GetBkThetaOffset() > 0)  len += PutAsciiParam((BIT8 *)",1", p_resp_parm+len);
           else                         len += PutAsciiParam((BIT8 *)",-1", p_resp_parm+len);

      return len;
   }
   else
   {
      error = OK;
      n     = 1;

      if( (p_cmd->parmv[0] >= 1) &&
          (p_cmd->parms[p_cmd->parmv[1]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[1]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetAlsWasteMode (FRONT, entry);
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 2) &&
          (p_cmd->parms[p_cmd->parmv[2]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[2]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetAlsFanOnOff (FRONT, entry);
            n     = 2;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 3) &&
          (p_cmd->parms[p_cmd->parmv[3]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[3]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetSyringeSize (FRONT, entry);
            n     = 3;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 4) &&
          (p_cmd->parms[p_cmd->parmv[4]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[4]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetExtendSolv(FRONT, entry);
            n     = 4;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 5) &&
          (p_cmd->parms[p_cmd->parmv[5]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[5]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetWashStop(FRONT, entry);
            n     = 5;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 6) &&
          (p_cmd->parms[p_cmd->parmv[6]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[6]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SolventSaverOnOff (FRONT, (ON_OFF)entry);
            n     = 6;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 7) &&
          (p_cmd->parms[p_cmd->parmv[7]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[7]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetAlsWasteMode (BACK, entry);
            n     = 7;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 8) &&
          (p_cmd->parms[p_cmd->parmv[8]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[8]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetAlsFanOnOff (BACK, entry);
            n     = 8;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 9) &&
          (p_cmd->parms[p_cmd->parmv[9]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[9]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetSyringeSize (BACK, entry);
            n     = 9;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 10) &&
          (p_cmd->parms[p_cmd->parmv[10]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[10]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetExtendSolv(BACK, entry);
            n     = 10;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 11) &&
          (p_cmd->parms[p_cmd->parmv[11]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[11]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetWashStop(BACK, entry);
            n     = 11;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 12) &&
          (p_cmd->parms[p_cmd->parmv[12]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[12]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SolventSaverOnOff (BACK, (ON_OFF)entry);
            n     = 12;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 13) &&
          (p_cmd->parms[p_cmd->parmv[13]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[13]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetBCR3of9OnOff (entry);
            n     = 13;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 14) &&
          (p_cmd->parms[p_cmd->parmv[14]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[14]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetBCR2of5OnOff (entry);
            n     = 14;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 15) &&
          (p_cmd->parms[p_cmd->parmv[15]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[15]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetBCRUPCOnOff (entry);
            n     = 15;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 16) &&
          (p_cmd->parms[p_cmd->parmv[16]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[16]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetBCRChecksumOnOff (entry);
            n     = 16;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 17) &&
          (p_cmd->parms[p_cmd->parmv[17]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[17]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetBCRPosition (entry);
            n     = 17;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 18) &&
          (p_cmd->parms[p_cmd->parmv[18]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[18]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetGripOffset  (entry);
            n     = 18;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 19) &&
          (p_cmd->parms[p_cmd->parmv[19]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[19]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetFrThetaOffset  (entry);
            n     = 19;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 20) &&
          (p_cmd->parms[p_cmd->parmv[20]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[20]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetBkThetaOffset  (entry);
            n     = 20;
         }
      }

      if (error != OK)
      {
         CmdErrorHandler(p_cmd,n,INVALID_PARAM);
      }

      return NO_RESPONSE;
   }

}

/***********************************************************************/
/* END FUNCTION: Do0xIC                                                */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XINJECT                                                */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS Inject, Sinject commands (handled by same code with    */
/*             Sinject global used to differentiate).                  */
/*                                                                     */
/***********************************************************************/

INT16 Do0XINJECT (CMD_TYPE *p_cmd, BIT8 *p_resp_parm, BIT8 sinject)
{
   INT32  front;
   INT32  back;
   UI_ERR error;
   BIT8   semi1;
   BIT8   semi2;
   BIT8   no_wait;

   no_wait = FALSE;
   semi1   = FALSE;
   semi2   = FALSE;
   front   = 0;
   back    = 0;
   error   = OK;

   if (p_cmd->parmv[0] >= 1)    /* param 1 is ; or front bottle# */
   {
      if (p_cmd->parms[p_cmd->parmv[1]] == ';') semi1 = TRUE;
      else   error = DecToInt(&p_cmd->parms[p_cmd->parmv[1]],0,&front);
   }

   if ( (error == OK) && (p_cmd->parmv[0] >= 2) ) /* param 2 is ; or back bottle# */
   {
      if (p_cmd->parms[p_cmd->parmv[2]] == ';')
      {
         if (semi1) semi2 = TRUE;
         else       semi1 = TRUE;
      }
      else
      {
         if (p_cmd->parms[p_cmd->parmv[2]] != 0)  /* skip null param */
         {
            if (semi1) error = DecToInt(&p_cmd->parms[p_cmd->parmv[2]],0,&back);
            else       error = (UI_ERR)Err_InvParameter;
         }
      }
   }

   if ( (error == OK) && (p_cmd->parmv[0] >= 3) ) /* param 3 is ; or back bottle#  or NOWAIT */
   {
      if (p_cmd->parms[p_cmd->parmv[3]] == ';')
      {
         if (semi2) error = (UI_ERR)Err_InvParameter;
         else       semi2 = TRUE;
      }
      else
      {
         if (semi2)
         {
            if (StrNCmp (&p_cmd->parms[p_cmd->parmv[3]], (BIT8 *)"NOWAIT", 6)) no_wait = TRUE;
            else   error = (UI_ERR) Err_InvParameter;
         }
         else /* Back bottle# */
         {
            if (p_cmd->parms[p_cmd->parmv[3]] != 0)           /* skip null param */
              error = DecToInt(&p_cmd->parms[p_cmd->parmv[3]],0,&back);
         }
      }
   }

   if ( (error == OK) && (p_cmd->parmv[0] >= 4) &&
        (p_cmd->parms[p_cmd->parmv[4]] != 0)       ) /* param 4 is ; or NOWAIT */
   {
      if (p_cmd->parms[p_cmd->parmv[4]] == ';')
      {
         if (semi2) error = (UI_ERR)Err_InvParameter;
         else       semi2 = TRUE;
      }
      else
      {
         if (semi2)
         {
            if (StrNCmp (&p_cmd->parms[p_cmd->parmv[4]], (BIT8 *)"NOWAIT", 6)) no_wait = TRUE;
            else   error = (UI_ERR) Err_InvParameter;
         }
         else /* invalid */
         {
            error = (UI_ERR) Err_InvParameter;
         }
      }
   }

   if ( (error == OK) && (p_cmd->parmv[0] >= 5) &&
        (p_cmd->parms[p_cmd->parmv[5]] != 0)       ) /* param 5 is NOWAIT */
   {
      if (StrNCmp (&p_cmd->parms[p_cmd->parmv[5]], (BIT8 *)"NOWAIT", 6)) no_wait = TRUE;
      else   error = (UI_ERR) Err_InvParameter;
   }

   if (error == OK)
   {
         error = InjectSample (front, back, no_wait, p_cmd, sinject, FALSE);

         if (error == OK) return NO_RESPONSE;  /* Delayed response sent at end of Inject cycle */
         else             return PutIntParam ((INT32)error, p_resp_parm, 0);
   }
   else
   {
      return PutIntParam ((INT32)error, p_resp_parm, 0);
   }
}

/***********************************************************************/
/* END FUNCTION: Do0xINJECT                                            */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XINJTYPE                                               */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS Inj_Type command                                       */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XINJTYPE (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT16  len;
   INT32  type;

   (void) p_cmd;

   switch (GetHonestInletType(pFRONT_INLET))
   {
   case COC:                 /* types copied from Mike's InletType function */
   case MANUAL_COC:
   case G_PTV:
   case CIS3:
      type = 1;
      break;

   case CIS4:
      type = 2;
      break;

   default:
      type = 0;
      break;
   }

   len = PutIntParam (type, p_resp_parm, 0);

   /* Back inlet type */
   switch (GetHonestInletType(pBACK_INLET))
   {
   case COC:                 /* types copied from Mike's InletType function */
   case MANUAL_COC:
   case G_PTV:
   case CIS3:
      type = 1;
      break;

   case CIS4:
      type = 2;
      break;

   default:
      type = 0;
      break;
   }

   len += PutAsciiParam((BIT8 *)",",p_resp_parm+len);
   len += PutIntParam (type, p_resp_parm+len, 0);

   return  len;

}

/***********************************************************************/
/* END FUNCTION: Do0xINJTYPE                                           */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XMIX                                                   */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: MIX command                                                */
/*                                                                     */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XMIX (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   UI_ERR   error;

   error = Mix (p_cmd);

   if (error == OK)
   {
      return NO_RESPONSE;  /* Delayed response sent at end of Mix     */
   }
   else
   {
      return PutIntParam ((INT32)error, p_resp_parm, 0);
   }
}

/***********************************************************************/
/* END FUNCTION: Do0xTRAY_POS                                          */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XMNT_LOG                                               */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS MNT_LOG command                                        */
/*                                                                     */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XMNT_LOG (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   (void) p_cmd;

   return PutIntParam ((INT32)Err_EndOfLog, p_resp_parm, 0);

}

/***********************************************************************/
/* END FUNCTION: Do0xMNT_LOG                                           */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XMOVE                                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS tray command to transport bottles.                     */
/*                                                                     */
/***********************************************************************/

UI_ERR ParseMoveParam (BTL_DEST *dest, INT32 *num, token_t *tok)
{
   *dest = NULLDEST;

   if (GetToken(tok) == IntToken)
   {
      *dest = TDEST;
      *num  = tok->u.ival;
      (void)GetToken(tok);
      return OK;
   }

   if (tok->typ == NameToken && (strcmp(tok->u.nval, "BCR") == 0))
   {
      *dest = BCRDEST;
      (void)GetToken(tok);
      return OK;
   }

   if (tok->typ == NameToken && (strcmp(tok->u.nval, "FRONT") == 0))
   {
      *dest = FDEST;

      if (GetToken(tok) == IntToken) {*num = tok->u.ival; (void)GetToken(tok);}
      else                                  *num = 1;

      return OK;
   }

   if (tok->typ == NameToken && ((strcmp(tok->u.nval, "BACK") == 0) ||
                                 (strcmp(tok->u.nval, "REAR") == 0)   ))
   {
      *dest = BDEST;

      if (GetToken(tok) == IntToken) {*num = tok->u.ival; (void)GetToken(tok);}
      else                                  *num = 1;

      return OK;
   }

   if (tok->typ == NameToken)    /* Name table not implemented */
   {
      return (UI_ERR)Err_UnknownName;
   }

   return OK;    /* everything else treated as NULL destination */
}


INT16 Do0XMOVE (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   UI_ERR   error;
   INT16    len;
   INT32    from;
   INT32    to;
   BTL_DEST from_dest;
   BTL_DEST to_dest;
   token_t  tok;

   error     = OK;
   from      = 0;
   to        = 0;
   from_dest = NULLDEST;
   to_dest   = NULLDEST;

   if (AnyAlsTray())
   {
      if (p_cmd->parmv[0] > 0 && p_cmd->parms[p_cmd->parmv[1]] != 0)  /* Null param ? */
      {
         tok.s = (char*) &p_cmd->parms[p_cmd->parmv[1]];
         error = ParseMoveParam (&from_dest, &from, &tok);

         if (error == OK && tok.typ != NullToken)
         {
            if (tok.typ == CommaToken) error = ParseMoveParam (&to_dest, &to, &tok);
            else                       error = (UI_ERR) Err_NoComma;
         }
      }
   }
   else
   {
      error = (UI_ERR)Err_NoTray;
   }

   if (error == OK)
   {
      error = MoveSample (from_dest, from, to_dest, to, p_cmd);
   }

   if (error == OK)
   {
      return NO_RESPONSE;  /* Delayed response sent at end of Move cycle */
   }
   else
   {
      len = PutIntParam ((INT32)error, p_resp_parm, 0);
      len += PutAsciiParam((BIT8 *)",1",p_resp_parm+len);   /* state = 1, parse error */
      return len;
   }
}

/***********************************************************************/
/* END FUNCTION: Do0xMOVE                                              */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XREAD_BCR                                              */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS READ_BCR Command                                       */
/*                                                                     */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XREAD_BCR (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   UI_ERR   error;
   INT16    len;
   INT32    from;
   INT32    to;
   BTL_DEST from_dest;
   BTL_DEST to_dest;
   token_t  tok;
   BIT8     reply;

   error      = (UI_ERR) Err_NoError;
   Barcode[0] = 0;
   reply      = TRUE;
   from       = 0;
   to         = 0;
   from_dest  = NULLDEST;
   to_dest    = NULLDEST;

   if (AnyAlsTray())
   {
      if (p_cmd->parmv[0] > 0 && p_cmd->parms[p_cmd->parmv[1]] != 0)  /* Null param ? */
      {
         tok.s = (char*) &p_cmd->parms[p_cmd->parmv[1]];
         (void) GetToken(&tok);

         if (tok.typ == NameToken && (strcmp(tok.u.nval, "FRONT")==0))
         {
            (void) strcpy ((char *)Barcode, (char *)TowerF.barcode);
         }
         else
         {
            if (tok.typ == NameToken && (strcmp(tok.u.nval, "BACK")==0))
            {
               (void) strcpy ((char *)Barcode, (char *)TowerB.barcode);
            }
            else
            {
               tok.s = (char*) &p_cmd->parms[p_cmd->parmv[1]];    /* back up */
               error = ParseMoveParam (&from_dest, &from, &tok);

               if (error == (UI_ERR)Err_NoError && (from_dest != NULLDEST && from_dest != TDEST))
               {
                  error = (UI_ERR)Err_UnknownName;
               }

               if (error == (UI_ERR)Err_NoError && tok.typ != NullToken)
               {
                  if (tok.typ == CommaToken) error = ParseMoveParam (&to_dest, &to, &tok);
                  else                       error = (UI_ERR)Err_NoComma;
               }

               if (error == (UI_ERR)Err_NoError)
               {
                  reply = FALSE;
                  error = ReadBarcode (from_dest, from, to_dest, to, p_cmd);
               }
            }
         }
      }
      else  /* Read bottle in reader */
      {
         reply = FALSE;
         error = ReadBarcode (from_dest, from, to_dest, to, p_cmd);
      }
   }
   else
   {
      error = (UI_ERR)Err_NoTray;
   }

   if (reply || error != (UI_ERR)Err_NoError)
   {
      len = PutIntParam ((INT32)error, p_resp_parm, 0);
      len += PutAsciiParam((BIT8 *)",1,\"", p_resp_parm+len);   /* state = 1 for all replies here  */
      len += PutAsciiParam(Barcode, p_resp_parm+len);           /* add barcode */
      len += PutAsciiParam((BIT8 *)"\"", p_resp_parm+len);      /* closing quote */
      return len;
   }
   else
   {
      return NO_RESPONSE;  /* Delayed response sent at end of read BCR   */
   }
}

/***********************************************************************/
/* END FUNCTION: Do0xREAD_BCR                                          */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XRTN_ALL                                               */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS RTN_ALL command                                        */
/*                                                                     */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XRTN_ALL (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   UI_ERR   error;

   error = ReturnAll (p_cmd);

   if (error == OK)
   {
      return NO_RESPONSE;  /* Delayed response sent at end of return all */
   }
   else
   {
      return PutIntParam ((INT32)error, p_resp_parm, 0);
   }
}

/***********************************************************************/
/* END FUNCTION: Do0xRTN_ALL                                           */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XSETPTS                                                */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS SETPTS command                                         */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/


UI_ERR SetTowerSetpoints (POSITION p, CMD_TYPE *p_cmd, BIT8 check_only, INT8 index)
{
   UI_ERR error;
   U_INT16 i;
   INT32  setpts[14];
   pALS_TBL als;

   error = OK;
   if (p == FRONT) als = &TowerF;
   else            als = &TowerB;

   INTERRUPTS_OFF;
      setpts[VolumeStop]  = als->setpts.volume_stop;
      setpts[Pumps]       = als->setpts.pumps;
      setpts[Viscosity]   = als->setpts.viscosity;
      setpts[SampleWash]  = als->setpts.sample_wash;
      setpts[PostWashA]   = als->setpts.post_wash_a;
      setpts[PostWashB]   = als->setpts.post_wash_b;
      setpts[SlowPlunger] = als->setpts.slow_plunger;
      setpts[PreDwell]    = als->setpts.pre_dwell;
      setpts[PostDwell]   = als->setpts.post_dwell;
      setpts[SkimEnable]  = als->setpts.skim_enable;
      setpts[SkimDepth]   = als->setpts.skim_depth;
      setpts[PreWashA]    = als->setpts.pre_wash_a;
      setpts[PreWashB]    = als->setpts.pre_wash_b;
   INTERRUPTS_ON;

   for (i=1; i<14; i++)
   {
      if (p_cmd->parmv[0] < i+index) break;                   /* no more setpts */
      if (p_cmd->parms[p_cmd->parmv[i+index]] == ';') break;  /* end of tower setpts */

      if (p_cmd->parms[p_cmd->parmv[i+index]] != 0)           /* skip null param */
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[i+index]], 0, &setpts[i]);

         if (error != OK) break;                        /* exit on scanner error */
      }
   }
             /* Range check, same as Mike's */
   if (/* (setpts[Enabled] < 0)   || (setpts[Enabled] > 1)     ||     Enabled - not in command  */
        (setpts[VolumeStop] < 1)  || (setpts[VolumeStop] > 50) ||  /* Pct or Volume Stop */
        (setpts[Pumps] < 0)       || (setpts[Pumps] > 15)      ||  /* Pumps       */
        (setpts[Viscosity] < 0)   || (setpts[Viscosity] > 7)   ||  /* Viscosity   */
        (setpts[SampleWash] < 0)  || (setpts[SampleWash] > 15) ||  /* SampleWash  */
        (setpts[PostWashA] < 0)   || (setpts[PostWashA] > 15)  ||  /* PostWashA   */
        (setpts[PostWashB] < 0)   || (setpts[PostWashB] > 15)  ||  /* PostWashB   */
        (setpts[SlowPlunger] < 0) || (setpts[SlowPlunger] > 1) ||  /* SlowPlunger */
        (setpts[PreDwell] < 0)    || (setpts[PreDwell] > 100)  ||  /* PreDwell    */
        (setpts[PostDwell] < 0)   || (setpts[PostDwell] > 100) ||  /* PostDwell   */
        (setpts[SkimEnable] < 0)  || (setpts[SkimEnable] > 1)  ||  /* SkimEnable  */
        (setpts[SkimDepth] < -20) || (setpts[SkimDepth] > 300) ||  /* Skim Depth  */
        (setpts[PreWashA] < 0)    || (setpts[PreWashA] > 15)   ||  /* PreWashA    */
        (setpts[PreWashB] < 0)    || (setpts[PreWashB] > 15)       /* PreWashB    */
      ) error = (UI_ERR) Err_SetptRange;

   /* Check volume stop for 6 max if old tower */
   if ((als->twr->tower_type != G4513) && (setpts[VolumeStop] > 6)) error = (UI_ERR) Err_SetptRange;

   if (!check_only && (error == OK))
   {
      SetCsiDefaults(als);

      if(als->twr->tower_type != G4513)
      {
         als->setpts.volume_stop  = setpts[VolumeStop];
      }
      else
      {
         als->setpts.volume_stop  = setpts[VolumeStop];
         als->setpts.volume_percent = setpts[VolumeStop];
      }

      if(als->setpts.pumps       != setpts[Pumps])
      {
         als->setpts.pumps        = setpts[Pumps];
/*       LogSetptChange(ALS_PUMPS, als->setpts.pumps, 0); */
      }

      if(als->setpts.viscosity   != setpts[Viscosity])
      {
         als->setpts.viscosity    = setpts[Viscosity];
/*       LogSetptChange(ALS_VISCOSITY, als->setpts.viscosity, 0);   */
      }

      if(als->setpts.sample_wash != setpts[SampleWash])
      {
         als->setpts.sample_wash  = setpts[SampleWash];
/*       LogSetptChange(ALS_SAMPLE_WASH, als->setpts.sample_wash, 0); */
      }

      if(als->setpts.post_wash_a != setpts[PostWashA])
      {
         als->setpts.post_wash_a  = setpts[PostWashA];
/*       LogSetptChange(ALS_POST_WASH_A, als->setpts.post_wash_a, 0);  */
      }

      if(als->setpts.post_wash_b != setpts[PostWashB])
      {
         als->setpts.post_wash_b  = setpts[PostWashB];
/*       LogSetptChange(ALS_POST_WASH_B, als->setpts.post_wash_b, 0);   */
      }

      if(als->setpts.slow_plunger != setpts[SlowPlunger])
      {
         als->setpts.slow_plunger = setpts[SlowPlunger];
         if (als->setpts.slow_plunger == 0)
         {
/*          LogSetptChange(ALS_SLOW_PLUNGER_OFF, 0, 0);       */
         }
         else
         {
/*          LogSetptChange(ALS_SLOW_PLUNGER_ON, 0, 0);        */
         }
      }

      if(als->setpts.pre_dwell   != setpts[PreDwell])
      {
         als->setpts.pre_dwell    = setpts[PreDwell];
/*       LogSetptChange(ALS_PRE_DWELL, als->setpts.pre_dwell, 0);  */
      }

      if(als->setpts.post_dwell  != setpts[PostDwell])
      {
         als->setpts.post_dwell   = setpts[PostDwell];
/*       LogSetptChange(ALS_POST_DWELL, als->setpts.post_dwell, 0); */
      }

      if(als->setpts.skim_enable != setpts[SkimEnable])
      {
         als->setpts.skim_enable  = setpts[SkimEnable];
         if (als->setpts.skim_enable == 0)
         {
/*          LogSetptChange(ALS_SKIM_ENABLE_OFF, 0, 0);             */
         }
         else
         {
/*          LogSetptChange(ALS_SKIM_ENABLE_ON, 0, 0);              */
         }
      }

      if(als->setpts.skim_depth  != setpts[SkimDepth])
      {
         als->setpts.skim_depth   = setpts[SkimDepth];
/*       LogSetptChange(ALS_SKIM_DEPTH, als->setpts.skim_depth, 0);  */
      }

      if(als->setpts.pre_wash_a  != setpts[PreWashA])
      {
         als->setpts.pre_wash_a   = setpts[PreWashA];
/*       LogSetptChange(ALS_PRE_WASH_A, als->setpts.pre_wash_a, 0);  */
      }

      if(als->setpts.pre_wash_b  != setpts[PreWashB])
      {
         als->setpts.pre_wash_b   = setpts[PreWashB];
/*       LogSetptChange(ALS_PRE_WASH_B, als->setpts.pre_wash_b, 0);  */
      }

   }

   return error;
}

UI_ERR SetTraySetpoints (CMD_TYPE *p_cmd, BIT8 check_only, INT8 index)
{
   INT32  temp[2];
   U_INT16 i;
   UI_ERR error;

   error = OK;

   INTERRUPTS_OFF;
      temp[0] = Tray_Enabled;
      temp[1] = BCR_Enabled;
   INTERRUPTS_ON;

   for (i=1; i<=2; i++)
   {
      if (p_cmd->parmv[0] < i+index) break;                   /* no more setpts */
      if (p_cmd->parms[p_cmd->parmv[i+index]] == ';') break;  /* end of tray setpts */

      if (p_cmd->parms[p_cmd->parmv[i+index]] != 0)           /* skip null param */
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[i+index]], 0, &temp[i-1]);

         if (error != OK) break;                        /* exit on scanner error */
      }
   }

   if ( (temp[0] < 0)  || (temp[0] > 1)  ||    /* Tray enabled */
        (temp[1] < 0)  || (temp[1] > 1)        /* BCR enabled */
      ) error = (UI_ERR) Err_SetptRange;

   if (!check_only && (error == OK))
   {
      if(Tray_Enabled != temp[0])
      {
         Tray_Enabled = temp[0];

         if (Tray_Enabled == 0)
         {
/*          LogSetptChange(TRAY_ENABLED_OFF, 0, 0);       */
         }
         else
         {
/*          LogSetptChange(TRAY_ENABLED_ON, 0, 0);        */
         }
      }

      if(BCR_Enabled != temp[1])
      {
         BCR_Enabled = temp[1];

         if (BCR_Enabled == 0)
         {
/*          LogSetptChange(BCR_ENABLED_OFF, 0, 0);       */
         }
         else
         {
/*          LogSetptChange(BCR_ENABLED_ON, 0, 0);        */
         }
      }
   }

   return error;
}


INT16 Do0XSETPTS (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   UI_ERR error;
   INT16   len;
   INT8    ib;
   INT8    it;

   error = OK;

   if( (p_cmd->parmv[0] == 1) && (p_cmd->parms[p_cmd->parmv[1]] == '?') )
   {
      len  = AddTowerSetpts (FRONT, p_resp_parm);
      len += PutAsciiParam((BIT8 *)";", p_resp_parm+len);
      len += AddTowerSetpts (BACK, p_resp_parm+len);
      len += PutAsciiParam((BIT8 *)";", p_resp_parm+len);
      len += AddTraySetpts (p_resp_parm+len);
      return len;
   }

   if( (p_cmd->parmv[0] == 1) &&
       (StrNCmp (&p_cmd->parms[p_cmd->parmv[1]], (BIT8 *)"DEFAULTS", 8) ) )
   {
      SetAlsDefaults();
/*    LogSetptChange(ALS_DEFAULTS, 0, 0);       */
   }
   else
   {
      /* First check if setpoint ok: */
      for (ib=1; ib<=p_cmd->parmv[0]; ib++)
      {
         if (p_cmd->parms[p_cmd->parmv[ib]] == ';') break;  /* end of f tower setpts */
      }

      for (it=ib+1; it<=p_cmd->parmv[0]; it++)
      {
         if (p_cmd->parms[p_cmd->parmv[it]] == ';') break;  /* end of b tower setpts */
      }

      error = SetTowerSetpoints (FRONT, p_cmd, TRUE, 0);
      if (error == OK) error = SetTowerSetpoints (BACK, p_cmd, TRUE, ib);
      if (error == OK) error = SetTraySetpoints (p_cmd, TRUE, it);

      /* If setpoints ok, install */
      if (error == OK)
      {
         error = SetTowerSetpoints (FRONT, p_cmd, FALSE, 0);
         error = SetTowerSetpoints (BACK, p_cmd, FALSE, ib);
         error = SetTraySetpoints (p_cmd, FALSE, it);
         Inj_Status &= ~ALS_PARAM_MODIFIED;
      }
   }

   return PutIntParam ((INT32)error, p_resp_parm, 0);
}

/***********************************************************************/
/* END FUNCTION: Do0xSETPTS                                            */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XSTATUS                                                */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS STATUS command                                         */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XSTATUS (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT16  len;
   BIT8   status;

   (void) p_cmd;

   /* Inj status */
   status = ((Tray_Busy+Inj_Busy)? 8 : 0) | Inj_Status;
   len = PutHexParam ((INT32)status, p_resp_parm);
   len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);

   /* Front status */
   if (TowerF.twr->present)
   {
      status = 1;
      if (TowerF.setpts.enabled) status += 2;
      status += TowerF.twr->ping[1] & 0x0f;
   }
   else
   {
      status = 0;
   }
   len += PutHexParam (status, p_resp_parm+len);
   len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);

   /* Back status */
   if (TowerB.twr->present)
   {
      status = 1;
      if (TowerB.setpts.enabled) status += 2;
      status += TowerB.twr->ping[1] & 0x0f;
   }
   else
   {
      status = 0;
   }
   len += PutHexParam (status, p_resp_parm+len);
   len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);

   /* Tray status */
   if (Tray)
   {
      status = 1;
      if (Tray_Enabled) status += 2;
      status += (Tray_Busy & TRAYBUSY)? 4 : 0;
   }
   else
   {
      status = 0;
   }
   len += PutHexParam (status, p_resp_parm+len);
   len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);

   /* BCR status */
   if (BCR_Type != 0)
   {
      status = 1;
      if (BCR_Enabled) status += 2;
      status += (Tray_Busy & BCRBUSY)? 4 : 0;
   }
   else
   {
      status = 0;
   }
   len += PutHexParam (status, p_resp_parm+len);
   len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);

   /* APG bus status */
   len += PutHexParam (ApgValue(), p_resp_parm+len);
   len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);

   /* Inject State */
   len += PutIntParam ((INT32)Inject_State, p_resp_parm+len, 0);

   return len;

}

/***********************************************************************/
/* END FUNCTION: Do0xSTATUS                                            */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XTRAY_POS                                              */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: TRAY_POS  command                                          */
/*                                                                     */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XTRAY_POS (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   UI_ERR   error;

   error = TrayPos (p_cmd);

   if (error == OK)
   {
      return NO_RESPONSE;  /* Delayed response sent at end of TrayPos */
   }
   else
   {
      return PutIntParam ((INT32)error, p_resp_parm, 0);
   }
}

/***********************************************************************/
/* END FUNCTION: Do0xTRAY_POS                                          */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XVSIX                                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS VSIF, VSIB commands                                    */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

/* Mike's parse routine, adjusted for Vireo */
UI_ERR ParseParams(CMD_TYPE *p_cmd, POSITION pos)
{
        INT16    found, val, tmp;
        INT16    csi[4];
const   param_t *p;
        pALS_TBL als;
        token_t  tok;

   tok.s = (char*) &p_cmd->parms[p_cmd->parmv[1]];

   if (pos == FRONT) als = &TowerF;
   else              als = &TowerB;

   csi[0] = als->csi.draw;
   csi[1] = als->csi.wash_disp;
   csi[2] = als->wash_volume;
   csi[3] = als->csi.inj_disp;

   (void)GetToken(&tok);
   while (tok.typ == NameToken) {
      found = 0;
      for (p = parray, tmp = 0; tmp <= 3; p++, tmp++)
         if (strcmp(tok.u.nval, p->pname)==0) {found = 1; break; };
            if (GetToken(&tok) != EqualToken) return (UI_ERR)Err_InvParameter;
            if (GetToken(&tok) != IntToken) return (UI_ERR)Err_InvParameter;
            if (found) {
               val = tok.u.ival;
               if (val < p->lbnd || val > p->ubnd) return (UI_ERR)Err_SetptRange;
               csi[tmp] = val; };
         (void)GetToken(&tok);
         if (tok.typ == CommaToken)  (void)GetToken(&tok);
   };
   if (tok.typ == NullToken)
   {
      als->csi.draw      = csi[0];
      als->csi.wash_disp = csi[1];
      als->wash_volume   = csi[2];
      als->csi.inj_disp  = csi[3];
      return (UI_ERR)Err_NoError;
   }
   else return (UI_ERR)Err_InvParameter;
}

INT16 Do0XVSIX (CMD_TYPE *p_cmd, BIT8 *p_resp_parm, POSITION p)
{
   UI_ERR error;
   INT16  len;

   if( (p_cmd->parmv[0] == 1) && (p_cmd->parms[p_cmd->parmv[1]] == '?') )
   {
      len = PutAsciiParam((BIT8 *)"draw=", p_resp_parm);
      len += PutIntParam (GetCsiDraw(p), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)" wsh_disp=", p_resp_parm+len);
      len += PutIntParam (GetCsiWashDisp(p), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)" wsh_vol=", p_resp_parm+len);
      len += PutIntParam (GetWashStop(p), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)" inj_disp=", p_resp_parm+len);
      len += PutIntParam (GetCsiInjDisp(p), p_resp_parm+len, 0);
      return len;
   }
   else
   {
      error = ParseParams(p_cmd, p);   /* use Mike's parsing */

      return PutIntParam ((INT32)error, p_resp_parm, 0);
   }


}

/***********************************************************************/
/* END FUNCTION: Do0XVSIX                                              */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0xVS                                                    */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS VS command                                             */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XVS (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT32  entry;
   UI_ERR error;
   INT16  len;
   U_INT16  n;

   if( (p_cmd->parmv[0] == 1) && (p_cmd->parms[p_cmd->parmv[1]] == '?') )
   {
      len = PutIntParam (GetCsiDraw(FRONT), p_resp_parm, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetCsiWashDisp(FRONT), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetWashStop(FRONT), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetCsiInjDisp(FRONT), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetCsiDraw(BACK), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetCsiWashDisp(BACK), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetWashStop(BACK), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetCsiInjDisp(BACK), p_resp_parm+len, 0);

      return len;
   }
   else
   {
      error = OK;
      n     = 1;

      if( (p_cmd->parmv[0] >= 1) &&
          (p_cmd->parms[p_cmd->parmv[1]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[1]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetCsiDraw (FRONT, entry);
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 2) &&
          (p_cmd->parms[p_cmd->parmv[2]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[2]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetCsiWashDisp (FRONT, entry);
            n     = 2;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 3) &&
          (p_cmd->parms[p_cmd->parmv[3]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[3]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetWashStop (FRONT, entry);
            n     = 3;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 4) &&
          (p_cmd->parms[p_cmd->parmv[4]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[4]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetCsiInjDisp(FRONT, entry);
            n     = 4;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 5) &&
          (p_cmd->parms[p_cmd->parmv[5]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[5]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetCsiDraw (BACK, entry);
            n     = 5;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 6) &&
          (p_cmd->parms[p_cmd->parmv[6]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[6]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetCsiWashDisp (BACK, entry);
            n     = 6;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 7) &&
          (p_cmd->parms[p_cmd->parmv[7]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[7]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetWashStop (BACK, entry);
            n     = 7;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 8) &&
          (p_cmd->parms[p_cmd->parmv[8]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[8]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetCsiInjDisp (BACK, entry);
            n     = 8;
         }
      }

      if (error != OK)
      {
         CmdErrorHandler(p_cmd,n,INVALID_PARAM);
      }

      return NO_RESPONSE;
   }
}

/***********************************************************************/
/* END FUNCTION: Do0xVS                                                */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0xTOWER                                                 */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS TOWER Command                                          */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

UI_ERR GetTower (CMD_TYPE *p_cmd)       /* Mike's TOWER parser, modified for Vireo */
{
   U_INT16 sel, rep;
   INT16   delay;
   token_t tok;

   tok.s = (char*) &p_cmd->parms[p_cmd->parmv[1]];

   if (GetToken(&tok) != NameToken) return (UI_ERR)Err_InvParameter;

   if (strcmp(tok.u.nval, "FRONT")==0) sel = 1;
   else     if (strcmp(tok.u.nval, "BACK")==0) sel = 0;
            else                               return (UI_ERR)Err_InvParameter;

   if (GetToken(&tok) != CharToken)              return (UI_ERR)Err_InvParameter;
   if (tok.u.cval != '\'' && tok.u.cval != '"')  return (UI_ERR)Err_InvParameter;
   if (GetToken(&tok) != NameToken)              return (UI_ERR)Err_InvParameter;
   if (strcmp(tok.u.nval, "IM")!=0)              return (UI_ERR)Err_InvParameter;
   if (GetToken(&tok) != IntToken)               return (UI_ERR)Err_InvParameter;

   if (tok.u.ival == 0) {rep = 1; delay = 0;}
   else
      if (tok.u.ival == 1)
      {
         if (GetToken(&tok) != IntToken) return (UI_ERR)Err_InvParameter;
         rep = tok.u.ival;
         if (GetToken(&tok) != IntToken) return (UI_ERR)Err_InvParameter;
         delay = tok.u.ival;
         if (rep   < ALS_MIN_REPS  || rep   > ALS_MAX_REPS  ||
             delay < ALS_MIN_DELAY || delay > ALS_MAX_DELAY   ) return (UI_ERR)Err_SetptRange;
      }
      else  return (UI_ERR)Err_InvParameter;

   if (sel) {TowerF.rep = rep;  TowerF.delay = delay;}
   else     {TowerB.rep = rep;  TowerB.delay = delay;};

   return (UI_ERR)Err_NoError;
}

INT16 Do0XTOWER (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   UI_ERR error;

   error = GetTower (p_cmd);   /* use Mike's parsing */

   return PutIntParam ((INT32)error, p_resp_parm, 0);
}

/***********************************************************************/
/* END FUNCTION: Do0xTOWER                                             */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0xTO                                                    */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS TO command, does 0xTOWER setpoints in IQ/Vireo format  */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

INT16 Do0XTO (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT32  entry;
   UI_ERR error;
   INT16  len;
   U_INT16  n;

   if( (p_cmd->parmv[0] == 1) && (p_cmd->parms[p_cmd->parmv[1]] == '?') )
   {
      len = PutIntParam (GetAlsTowerReps(FRONT), p_resp_parm, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetAlsTowerDelay(FRONT), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetAlsTowerReps(BACK), p_resp_parm+len, 0);
      len += PutAsciiParam((BIT8 *)",", p_resp_parm+len);
      len += PutIntParam (GetAlsTowerDelay(BACK), p_resp_parm+len, 0);

      return len;
   }
   else
   {
      error = OK;
      n     = 1;

      if( (p_cmd->parmv[0] >= 1) &&
          (p_cmd->parms[p_cmd->parmv[1]] != 0) )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[1]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetAlsTowerReps (FRONT, entry);
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 2) &&
          (p_cmd->parms[p_cmd->parmv[2]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[2]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetAlsTowerDelay (FRONT, entry);
            n     = 2;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 3) &&
          (p_cmd->parms[p_cmd->parmv[3]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[3]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetAlsTowerReps (BACK, entry);
            n     = 3;
         }
      }

      if( (error == OK) && (p_cmd->parmv[0] >= 4) &&
          (p_cmd->parms[p_cmd->parmv[4]] != 0)      )
      {
         error = DecToInt(&p_cmd->parms[p_cmd->parmv[4]],0,&entry);
         if ((U_INT16)error == 0 )
         {
            error = SetAlsTowerDelay (BACK, entry);
            n     = 4;
         }
      }

      if (error != OK)
      {
         CmdErrorHandler(p_cmd,n,INVALID_PARAM);
      }

      return NO_RESPONSE;
   }
}

/***********************************************************************/
/* END FUNCTION: Do0xTO                                                */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: Do0XWFIL                                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: ALS WFIL   command                                         */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/


INT16 AddTowerSetpts (POSITION p, BIT8 *string)
{
   U_INT16 i;
   INT16   len;
   INT32   setpts[14];
   pALS_TBL als;

   if (p == FRONT) als = &TowerF;
   else            als = &TowerB;

   len = 0;

   INTERRUPTS_OFF;
/*    setpts[Enabled]     = als->setpts.enabled;     Not part of SETPTS cmd */
      setpts[VolumeStop]  = als->setpts.volume_stop;
      setpts[Pumps]       = als->setpts.pumps;
      setpts[Viscosity]   = als->setpts.viscosity;
      setpts[SampleWash]  = als->setpts.sample_wash;
      setpts[PostWashA]   = als->setpts.post_wash_a;
      setpts[PostWashB]   = als->setpts.post_wash_b;
      setpts[SlowPlunger] = als->setpts.slow_plunger;
      setpts[PreDwell]    = als->setpts.pre_dwell;
      setpts[PostDwell]   = als->setpts.post_dwell;
      setpts[SkimEnable]  = als->setpts.skim_enable;
      setpts[SkimDepth]   = als->setpts.skim_depth;
      setpts[PreWashA]    = als->setpts.pre_wash_a;
      setpts[PreWashB]    = als->setpts.pre_wash_b;
   INTERRUPTS_ON;

   for (i=1; i<14; i++)
   {
      len += PutIntParam (setpts[i], string+len, 0);
      len += PutAsciiParam((BIT8 *)",", string+len);
   }

   return len - 1;
}


INT16 AddTraySetpts (BIT8 *string)
{
   INT16   len;

   len = 0;

   len += PutIntParam (Tray_Enabled, string+len, 0);
   len += PutAsciiParam((BIT8 *)",", string+len);
   len += PutIntParam (BCR_Enabled, string+len, 0);

   return len;
}


INT16 Do0XWFIL (CMD_TYPE *p_cmd, BIT8 *p_resp_parm)
{
   INT16  len;

   (void) p_cmd;

   len = PutAsciiParam((BIT8 *)"SETPTS ", p_resp_parm);

   len += AddTowerSetpts (FRONT, p_resp_parm+len);

   len += PutAsciiParam((BIT8 *)";", p_resp_parm+len);

   len += AddTowerSetpts (BACK, p_resp_parm+len);

   len += PutAsciiParam((BIT8 *)";", p_resp_parm+len);

   len += AddTraySetpts (p_resp_parm+len);

   return len;

}

/***********************************************************************/
/* END FUNCTION: Do0xWFIL                                              */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION: _0XOpcodes                                                */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: calls routines needed to implement the 0X commands.        */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* FILE SCOPE STATICS USED:                                            */
/*                                                                     */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

INT16 _0XOpcodes(CMD_TYPE  *p_cmd,BIT8  *p_resp_parm,U_INT16 max_resp_len)
{

   /* WARNING!!!!                                                     */
   /*   ONLY 0x commands can have extended opcodes.  In handling the  */
   /*   reply buffer,  the opcode length is calculated inside of the  */
   /*   response buffer (see hostutil.c).  S1xxRD command does not    */
   /*   use a space after the opcode, but we guarantee all 0x cmds    */
   /*   will have a space so the search for the end of the opcode     */
   /*   can work.                                                     */

   INT16  parm_len;

   (void) max_resp_len;

   parm_len = NO_RESPONSE;

   switch( p_cmd->opcode.int_op )
   {
      case  MAKEINT('*','I'):
        parm_len = Do0XOldId(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('C','O'):
        parm_len = Do0XCO(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('C','P'):
        if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"CPI1a", 5) )
           parm_len = Do0XCPI1a(p_cmd, p_resp_parm);
        else
        if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"CPI1", 4) )
        {
           parm_len = Do0XCPI1(p_cmd, p_resp_parm);
        }
        else
        {
           if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"CPI2a", 5) )
              parm_len = Do0XCPI2a(p_cmd, p_resp_parm);
           else
           if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"CPI2", 4) )
           {
              parm_len = Do0XCPI2(p_cmd, p_resp_parm);
           }
           else
           {
              if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"CPTRa", 5) )
                 parm_len = Do0XCPTRa(p_cmd, p_resp_parm);
              else
              if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"CPTR", 4) )
              {
                 parm_len = Do0XCPTR(p_cmd, p_resp_parm);
              }
              else
              {
                 CmdErrorHandler(p_cmd,0,INVALID_OP);
              }
           }
        }
        break;

      case  MAKEINT('D','A'):
        parm_len = Do0XDA(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('E','R'):
        parm_len = Do0XERROR_STR(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('H','O'):
        parm_len = Do0XHOST_CTL (p_cmd, p_resp_parm);
        break;

      case  MAKEINT('I','C'):
        parm_len = Do0XIC(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('I','D'):
        if (PE_Defect_Fix != OFF)
        {
           /* Sampler Model Number with current firmware revision */
           parm_len  = PutAsciiParam((BIT8 *)"G2612", p_resp_parm);
           parm_len += TransferVersion( p_resp_parm+parm_len );
        }
        else
        {
           parm_len = DoCCID(p_resp_parm);
        }
        break;

      case  MAKEINT('I','N'):
        if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"INJ_ABORT", 9) )
        {
           AbortInject();
           parm_len = NO_RESPONSE;
        }
        else
        {
           if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"INJ_CONT", 8) )
           {
              No_Wait  = TRUE;
              parm_len = NO_RESPONSE;
           }
           else
           {
              if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"INJECT", 6) )
              {
                 /* send FALSE for INJECT (INJECT, SINJECT control) */
                 parm_len = Do0XINJECT(p_cmd, p_resp_parm, FALSE);
              }
              else
              {
                 if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"INJ_TYPE", 8) )
                 {
                    parm_len = Do0XINJTYPE(p_cmd, p_resp_parm);
                 }
                 else
                 {
                    /* Make INJ_CONFIG return no response as in 6890 Plus */
                    if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"INJ_CONFIG", 10) )
                           parm_len = NO_RESPONSE;
                    else   CmdErrorHandler(p_cmd,0,INVALID_OP);
                 }
              }
           }
        }
        break;

      case  MAKEINT('M','I'):
        parm_len = Do0XMIX(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('M','N'):
        parm_len = Do0XMNT_LOG(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('M','O'):
        parm_len = Do0XMOVE(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('R','E'):
        parm_len = Do0XREAD_BCR(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('R','T'):
        parm_len = Do0XRTN_ALL(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('S','E'):
        parm_len = Do0XSETPTS(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('S','I'):
        /* send TRUE for SINJECT (INJECT, SINJECT control) */
        parm_len = Do0XINJECT(p_cmd, p_resp_parm, TRUE);
        break;

      case  MAKEINT('S','T'):
        if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"STOP", 4) )
        {
           StopInjector();
           parm_len = NO_RESPONSE;
        }
        else
        {
           if ((StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"ST", 2) )       ||
               (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"STATUS", 6) )     )
           {
              parm_len = Do0XSTATUS(p_cmd, p_resp_parm);
           }
           else
           {
              CmdErrorHandler(p_cmd,0,INVALID_OP);
           }
        }
        break;

      case  MAKEINT('T','O'):                         /* TOWER Command */
        if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"TOWER", 5) )
        {
           parm_len = Do0XTOWER(p_cmd, p_resp_parm);
        }
        else
        {
           parm_len = Do0XTO(p_cmd, p_resp_parm);
        }
        break;

      case  MAKEINT('T','R'):
        parm_len = Do0XTRAY_POS(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('V','S'):
        if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"VSIF", 4) )
        {
           parm_len = Do0XVSIX(p_cmd, p_resp_parm, FRONT);
        }
        else
        {
           if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"VSIB", 4) )
           {
              parm_len = Do0XVSIX(p_cmd, p_resp_parm, BACK);
           }
           else
           {
              if (StrNCmp (p_cmd->opcode.char_op, (BIT8 *)"VS", 2) )
              {
                 parm_len = Do0XVS(p_cmd, p_resp_parm);
              }
              else
              {
                 CmdErrorHandler(p_cmd,0,INVALID_OP);
              }
           }
        }
        break;

      case  MAKEINT('W','F'):
        parm_len = Do0XWFIL(p_cmd, p_resp_parm);
        break;

      case  MAKEINT('E','O'):
        parm_len = Do0xEO(p_cmd, p_resp_parm);
        break;

      default:
         CmdErrorHandler(p_cmd,0,INVALID_OP);
         break;
   }

   return parm_len;
}


/***********************************************************************/
/* END FUNCTION: _0XOpcodes                                            */
/***********************************************************************/




/***********************************************************************/
/* FUNCTION: _0X_Cmds                                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* WARNINGS:                                                           */
/*                                                                     */
/***********************************************************************/

void _0X_Cmds(void)
{
   ExecCmds (&_0X_Cmd_Q, _0XOpcodes);
}

/***********************************************************************/
/* END FUNCTION: _0X_Cmds                                              */
/***********************************************************************/

